﻿using ByHand.Services.Code;
using ByHand.Services.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;

namespace BackEnd.Controllers
{
    public class UploadController : Controller
    {
        private readonly IProductService _ProductService;
        private readonly IProviderService _ProviderService;
        public UploadController(IProductService ProductService, IProviderService ProviderService)
        {
            _ProductService = ProductService;
            _ProviderService = ProviderService;
        }
        private string StorageRoot
        {
            get { return Path.Combine(Server.MapPath("~/Files")); }
        }
        public static string GetStorage(int id, int type)
        {
            var webRootPath = System.Web.HttpContext.Current.Server.MapPath("~");
            var foldername = "";
            switch (type)
            {
                case 1: foldername = "../Files"; break;
                case 2: foldername = "../Files/Logos"; break;
                case 4: foldername = "../Files/Backgrounds"; break;
                default: foldername = "../Files"; break;
            }
            var file = Path.GetFullPath(Path.Combine(webRootPath, foldername));
            if (!Directory.Exists(file))
            {
                Directory.CreateDirectory(file);
            }
            var specificfile = file + "/" + id;
            if (!Directory.Exists(specificfile))
            {
                Directory.CreateDirectory(specificfile);
            }
            return Path.GetFullPath(Path.Combine(webRootPath, foldername + "/" + id + "/"));
        }
        public ActionResult Index(int id, int type)
        {
            FormsAuthentication.SetAuthCookie("dsgbsd", false);
            ViewData["id"] = id;
            ViewData["type"] = type;
            var maxfile = 6;
            if (type != 1) maxfile = 1;
            ViewData["maxfile"] = maxfile;
            return PartialView();
        }

        public ActionResult Test()
        {
            try
            {
                var files =
                new DirectoryInfo(jQuery_File_Upload.MVC3.Upload.UploadHandler.GetStorage(2))
                    .GetFiles("*", SearchOption.TopDirectoryOnly)
                    .Where(f => !f.Attributes.HasFlag(FileAttributes.Hidden))
                    .Select(f => f.Name)
                    .FirstOrDefault();
                if (System.IO.File.Exists(jQuery_File_Upload.MVC3.Upload.UploadHandler.GetStorage(2) + files))
                {
                    System.IO.File.Delete(jQuery_File_Upload.MVC3.Upload.UploadHandler.GetStorage(2));
                }
            }
            catch (Exception e)
            {

                return Json(e.Message, JsonRequestBehavior.AllowGet);
            }
            return Json(true, JsonRequestBehavior.AllowGet);
        }

        //DONT USE THIS IF YOU NEED TO ALLOW LARGE FILES UPLOADS
        [HttpGet]
        public void Delete(string id, int type, string filename)
        {
            var productid = Convert.ToInt32(id);
            var filePath = GetStorage(productid, type) + filename;
            if (type == 1)
            {
                var product = _ProductService.GetById(productid);
                var list = new List<string>();
                list.Add(filename);
                if (product != null)
                {
                    _ProductService.MaintainProductImages(product, list, false);
                    _ProductService.Update(product);
                }
            }
            else
            {
                var provider = _ProviderService.GetById(productid);
                if (type == 2) provider.LogoImage = "";
                else provider.ImageBackground = "";
                _ProviderService.Update(provider);
            }

            if (System.IO.File.Exists(filePath))
            {
                System.IO.File.Delete(filePath);
            }
        }

        //DONT USE THIS IF YOU NEED TO ALLOW LARGE FILES UPLOADS
        [HttpGet]
        public void Download(string id, int type, string filename)
        {
            var productid = Convert.ToInt32(id);
            var filePath = GetStorage(productid, type) + filename;

            var context = HttpContext;

            if (System.IO.File.Exists(filePath))
            {
                context.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
                context.Response.ContentType = "application/octet-stream";
                context.Response.ClearContent();
                context.Response.WriteFile(filePath);
            }
            else
                context.Response.StatusCode = 404;
        }
        public ActionResult LoadFile(string id, string filename, int type)
        {
            var productid = Convert.ToInt32(id);
            var file = new DirectoryInfo(GetStorage(productid, type))
                     .GetFiles("*", SearchOption.TopDirectoryOnly)
                     .Where(f => !f.Attributes.HasFlag(FileAttributes.Hidden) && f.Name.Equals(filename))
                     .Select(f => new ViewDataUploadFilesResult()
                     {
                         name = f.Name,
                         size = (int)f.Length,
                         type = "image/png",
                         ProductID = productid,
                         url = "/Upload/Download?type=" + type + "&id=" + id + "&filename=" + Path.GetFileName(f.FullName),
                         delete_url = "/Upload/Delete?type=" + type + "&id=" + id + "&filename=" + Path.GetFileName(f.FullName),
                         thumbnail_url = @"data:image/png;base64," + EncodeFile(f.FullName),
                         delete_type = "GET",
                     }).SingleOrDefault();
            var r = new List<ViewDataUploadFilesResult>();
            if (file != null)
            {
                r.Add(file);
            }
            return Json(r, JsonRequestBehavior.AllowGet);
        }
        //DONT USE THIS IF YOU NEED TO ALLOW LARGE FILES UPLOADS
        public ActionResult UploadFiles(int id, int type)
        {
            var r = new List<ViewDataUploadFilesResult>();
            foreach (string file in Request.Files)
            {
                var statuses = new List<ViewDataUploadFilesResult>();
                var headers = Request.Headers;

                if (string.IsNullOrEmpty(headers["X-File-Name"]))
                {
                    UploadWholeFile(Request, statuses, id, type);
                }
                else
                {
                    UploadPartialFile(headers["X-File-Name"], Request, statuses, id, type);
                }
                if (type == 1)
                {
                    var product = _ProductService.GetById(id);
                    var list = new List<string>();
                    var filename = "";
                    foreach (var item in statuses)
                    {
                        filename = item.name;

                        list.Add(Utility.CreateImageUrl(filename, id, 1));

                    }
                    if (product != null)
                    {
                        _ProductService.MaintainProductImages(product, list, true);
                        _ProductService.Update(product);
                    }
                }
                else
                {
                    var provider = _ProviderService.GetById(id);
                    var filename = "";
                    if (type == 2)
                    {
                        filename = statuses[0].name;
                        filename = Utility.CreateImageUrl(filename, id, 2);
                        provider.LogoImage = filename;
                    }
                    else
                    {
                        filename = statuses[0].name;
                        filename = Utility.CreateImageUrl(filename, id, 4);
                        provider.ImageBackground = filename;
                    }
                    _ProviderService.Update(provider);
                }

                JsonResult result = Json(statuses);
                result.ContentType = "text/plain";

                return result;
            }

            return Json(r, JsonRequestBehavior.AllowGet);
        }

        private string EncodeFile(string fileName)
        {
            return Convert.ToBase64String(System.IO.File.ReadAllBytes(fileName));
        }

        //DONT USE THIS IF YOU NEED TO ALLOW LARGE FILES UPLOADS
        //Credit to i-e-b and his ASP.Net uploader for the bulk of the upload helper methods - https://github.com/i-e-b/jQueryFileUpload.Net
        private void UploadPartialFile(string fileName, HttpRequestBase request, List<ViewDataUploadFilesResult> statuses, int id, int type)
        {
            if (request.Files.Count != 1) throw new HttpRequestValidationException("Attempt to upload chunked file containing more than one fragment per request");
            var file = request.Files[0];
            var inputStream = file.InputStream;

            var fullName = GetStorage(id, type) + Path.GetFileNameWithoutExtension(fileName) + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + Path.GetExtension(fileName);

            using (var fs = new FileStream(fullName, FileMode.Append, FileAccess.Write))
            {
                var buffer = new byte[1024];

                var l = inputStream.Read(buffer, 0, 1024);
                while (l > 0)
                {
                    fs.Write(buffer, 0, l);
                    l = inputStream.Read(buffer, 0, 1024);
                }
                fs.Flush();
                fs.Close();
            }
            statuses.Add(new ViewDataUploadFilesResult()
            {
                name = Path.GetFileName(fullName),
                size = file.ContentLength,
                type = file.ContentType,
                ProductID = id,
                url = "/Upload/Download?type=" + type + "&id=" + id + "&filename=" + Path.GetFileName(fullName),
                delete_url = "/Upload/Delete?type=" + type + "&id=" + id + "&filename" + Path.GetFileName(fullName),
                thumbnail_url = @"data:image/png;base64," + EncodeFile(fullName),
                delete_type = "GET",
            });
        }

        //DONT USE THIS IF YOU NEED TO ALLOW LARGE FILES UPLOADS
        //Credit to i-e-b and his ASP.Net uploader for the bulk of the upload helper methods - https://github.com/i-e-b/jQueryFileUpload.Net
        private void UploadWholeFile(HttpRequestBase request, List<ViewDataUploadFilesResult> statuses, int id, int type)
        {
            for (int i = 0; i < request.Files.Count; i++)
            {
                var file = request.Files[i];

                var fullPath = GetStorage(id, type) + Path.GetFileNameWithoutExtension(file.FileName) + "_" + DateTime.Now.ToString("yyyyMMddHHmmssfff") + Path.GetExtension(file.FileName);

                file.SaveAs(fullPath);

                statuses.Add(new ViewDataUploadFilesResult()
                {
                    name = Path.GetFileName(fullPath),
                    size = file.ContentLength,
                    type = file.ContentType,
                    url = "/Upload/Download?type=" + type + "&id=" + id + "&filename=" + Path.GetFileName(fullPath),
                    delete_url = "/Upload/Delete?type=" + type + "&id=" + id + "&filename=" + Path.GetFileName(fullPath),
                    thumbnail_url = @"data:image/png;base64," + EncodeFile(fullPath),
                    delete_type = "GET",
                });
            }
        }

        private List<ViewDataUploadFilesResult> ListCurrentFiles(int id, int type)
        {
            var files =
                new DirectoryInfo(GetStorage(id, type))
                    .GetFiles("*", SearchOption.TopDirectoryOnly)
                    .Where(f => !f.Attributes.HasFlag(FileAttributes.Hidden))
                    .Select(f => new ViewDataUploadFilesResult()
                    {
                        name = f.Name,
                        size = (int)f.Length,
                        type = "image/png",
                        ProductID = id,
                        url = "/Upload/Download?type=" + type + "&id=" + id + "&filename=" + Path.GetFileName(f.FullName),
                        delete_url = "/Upload/Delete?type=" + type + "&id=" + id + "&filename" + Path.GetFileName(f.FullName),
                        thumbnail_url = @"data:image/png;base64," + EncodeFile(f.FullName),
                        delete_type = "GET",
                    })
                    .ToArray();
            var images = "";
            var returnfiles = new List<ViewDataUploadFilesResult>();
            if (type == 1)
            {
                var product = _ProductService.GetById(id);
                images = product.ImagePath;
            }
            else
            {
                var provider = _ProviderService.GetById(id);
                if (type == 2)
                {
                    images = provider.LogoImage;
                }
                else
                {
                    images = provider.ImageBackground;
                }
            }
            if (string.IsNullOrWhiteSpace(images)) images = "";
            foreach (var item in files)
            {

                if (images.Contains(item.name))
                {
                    returnfiles.Add(item);
                }
            }
            return returnfiles;
        }

        public ActionResult Count(int id, int type)
        {
            var files =
      new DirectoryInfo(GetStorage(id, type))
          .GetFiles("*", SearchOption.TopDirectoryOnly)
          .Where(f => !f.Attributes.HasFlag(FileAttributes.Hidden))
          .Select(f => new ViewDataUploadFilesResult()
          {
              name = f.Name,
              size = (int)f.Length,
              type = "image/png",
              ProductID = id,
              url = "/Upload/Download?type=" + type + "&id=" + id + "&filename=" + Path.GetFileName(f.FullName),
              delete_url = "/Upload/Delete?type=" + type + "&id=" + id + "&filename" + Path.GetFileName(f.FullName),
              thumbnail_url = @"data:image/png;base64," + EncodeFile(f.FullName),
              delete_type = "GET",
          })
          .ToArray();
            var returnfiles = new List<ViewDataUploadFilesResult>();
            if (type == 1)
            {
                var product = _ProductService.GetById(id);
                var images = product.ImagePath;
                if (string.IsNullOrWhiteSpace(images)) images = "";
                if (product != null)
                {
                    foreach (var item in files)
                    {

                        if (images.Contains(item.name))
                        {
                            returnfiles.Add(item);
                        }
                    }
                }
            }
            else
            {
                var provider = _ProviderService.GetById(id);
                var images = provider.LogoImage;
                if (type == 4) images = provider.ImageBackground;
                if (string.IsNullOrWhiteSpace(images)) images = "";
                if (provider != null)
                {
                    foreach (var item in files)
                    {

                        if (images.Contains(item.name))
                        {
                            returnfiles.Add(item);
                        }
                    }
                }
            }

            var names = returnfiles.Select(f => f.name).ToArray();
            return Json(new { count = returnfiles.Count, array = names }, JsonRequestBehavior.AllowGet);
        }

    }
    public class ViewDataUploadFilesResult
    {
        public string name { get; set; }
        public int size { get; set; }
        public string type { get; set; }
        public string url { get; set; }
        public string delete_url { get; set; }
        public string thumbnail_url { get; set; }
        public string delete_type { get; set; }
        public int ProductID { get; set; }
    }
}
